#import "BWConfigTemplate.h"

static NSString *g_applicationName;

@interface BWConfigTemplate (ForwardReferences)

- (id) initWithCategory: (NSString *) categoryName
                   name: (NSString *) name;
- (void) load;

@end // BWConfigTemplate



@implementation BWConfigTemplate

+ (void) setApplicationName: (NSString *) appName
{
    [g_applicationName release];
    g_applicationName = [appName copy];

} // setApplicationName



+ (BWConfigTemplate *) newTemplateInCategory: (NSString *) categoryName
                                        name: (NSString *) templateName
{
    BWConfigTemplate *template;
    template = [[self alloc] initWithCategory: categoryName
                             name: templateName];

    return ([template autorelease]);

} // newTemplateInCategory


+ (NSString *) appSupportDirectoryPath
{
    NSArray *directories;
    directories = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
                                                       NSUserDomainMask, YES);
    
    NSString *path;
    path = [NSString stringWithFormat: @"%@/Application Support/Borkware/%@",
                     [directories objectAtIndex: 0], g_applicationName];

    return (path);

} // appSupportDirectoryPath


+ (NSString *) categoryDirectoryPathForCategory: (NSString *) cat
{
    NSString *appSupportPath = [self appSupportDirectoryPath];

    NSString *path;
    path = [NSString stringWithFormat: @"%@/%@", appSupportPath, cat];

    return (path);

} // categoryDirectoryPath


+ (void) createAppSupportDirectoryIfNeeded
{
    NSString *appSupportPath = [self appSupportDirectoryPath];

    // I feel bad about not checking the return value.  But it's pretty
    // worthless for trying to figure out what's wrong
    [[NSFileManager defaultManager]
        createDirectoryAtPath: appSupportPath
        attributes: nil];
    
} // createAppSupportDirectoryIfNeeded


- (void) createAppSupportDirectoryIfNeeded
{
    [BWConfigTemplate createAppSupportDirectoryIfNeeded];

} // createAppSupportDirectoryIfNeeded



+ (void) createCategoryDirectoryIfNeededForCategory: (NSString *) cat
{
    [self createAppSupportDirectoryIfNeeded];

    NSString *categoryPath = [self categoryDirectoryPathForCategory: cat];

    [[NSFileManager defaultManager]
        createDirectoryAtPath: categoryPath
        attributes: nil];
    
} // createCategoryDirectoryIfNeeded


+ (NSArray *) namesForCategory: (NSString *) categoryName
{
    NSMutableArray *names = [NSMutableArray array];

    [self createAppSupportDirectoryIfNeeded];
    [self createCategoryDirectoryIfNeededForCategory: categoryName];

    NSString *path = [self categoryDirectoryPathForCategory: categoryName];

    NSDirectoryEnumerator *enumerator;
    enumerator = [[NSFileManager defaultManager] enumeratorAtPath: path];

    NSString *filepath;
    while (filepath = [enumerator nextObject]) {
        [names addObject: [[filepath lastPathComponent] 
                              stringByDeletingPathExtension]];
    }
    [names sortUsingSelector: @selector(caseInsensitiveCompare:)];

    return (names);

} // namesForCategory


+ (BWConfigTemplate *) loadTemplateForCategory: (NSString *) categoryName
                                          name: (NSString *) templateName
{
    BWConfigTemplate *template;
    template = [self newTemplateInCategory: categoryName
                     name: templateName];

    [template load];

    return (template);

} // loadTemplateForCategory


- (id) initWithCategory: (NSString *) c
                   name: (NSString *) n
{

    if ([super init] == nil) {
        return (nil);
    }

    category = [c copy];
    name = [n copy];
    attributes = [[NSMutableDictionary alloc] init];

    return (self);

} // initWithCategory


- (void) dealloc
{
    [category release];
    [name release];
    [attributes release];

    [super dealloc];

} // dealloc


- (NSString *) appSupportDirectoryPath
{
    return ([BWConfigTemplate appSupportDirectoryPath]);

} // appSupportDirectoryPath


- (NSString *) categoryDirectoryPath
{
    return ([BWConfigTemplate categoryDirectoryPathForCategory: category]);

} // categoryDirectoryPath


- (NSString *) templateFilePath
{
    NSString *path;
    path = [NSString stringWithFormat: @"%@/%@.plist",
                     [self categoryDirectoryPath], name];

    return (path);

} // templateFilePath



- (void) createCategoryDirectoryIfNeeded
{
    [BWConfigTemplate createCategoryDirectoryIfNeededForCategory: category];
} // createCategoryDirectoryIfNeeded



// client is done making changes, save that pupper
- (void) save
{
    [self createCategoryDirectoryIfNeeded];

    NSData *data;
    data = [NSPropertyListSerialization
               dataFromPropertyList: attributes
               format: NSPropertyListXMLFormat_v1_0
               errorDescription: nil];

    [data writeToFile: [self templateFilePath]
          atomically: YES];

} // save


- (void) load
{
    NSData *data;
    data = [NSData dataWithContentsOfFile: [self templateFilePath]];
    
    if (data != nil) {
        [attributes release];
        attributes = [NSPropertyListSerialization
                         propertyListFromData: data
                         mutabilityOption: NSPropertyListMutableContainers
                         format: nil
                         errorDescription: nil];
        [attributes retain];
    }

} // load


// clients use KVC for setting values

- (id) valueForUndefinedKey: (NSString *) key
{
    id value;
    value = [attributes valueForKey: key];

    return (value);

} // valueForUndefinedKey


- (void) setValue: (id) value  forUndefinedKey: (NSString *) key
{
    [attributes setValue: value  forKey: key];

} // setValue


- (void) setFloatValue: (float) value
                forKey: (NSString *) key
{
    NSNumber *number = [NSNumber numberWithFloat: value];
    [self setValue: number  forKey: key];

} // setFloatValue


- (float) floatValueForKey: (NSString *) key
{
    float value = 0.0;

    NSNumber *number = [self valueForKey: key];

    if (number != nil) {
        value = [number floatValue];
    }

    return (value);

} // floatValueForKey


- (void) setIntValue: (int) value
              forKey: (NSString *) key
{
    NSNumber *number = [NSNumber numberWithInt: value];
    [self setValue: number  forKey: key];

} // setIntValue


- (int) intValueForKey: (NSString *) key
{
    int value = 0.0;

    NSNumber *number = [self valueForKey: key];

    if (number != nil) {
        value = [number intValue];
    }

    return (value);

} // intValueForKey


- (void) setBoolValue: (BOOL) value
               forKey: (NSString *) key
{
    NSNumber *number = [NSNumber numberWithBool: value];
    [self setValue: number  forKey: key];
    
} // setBoolValue


- (BOOL) boolValueForKey: (NSString *) key
{
    BOOL value = NO;

    NSNumber *number = [self valueForKey: key];

    if (number != nil) {
        value = [number boolValue];
    }

    return (value);

} // boolValueForKey


- (void) setObjectValue: (id<NSCoding>) value
                 forKey: (NSString *) key
{
    NSData *data;
    data = [NSArchiver archivedDataWithRootObject: value];
    
    [self setValue: data
          forKey: key];

} // setObjectValue


- (id) objectValueForKey: (NSString *) key
{
    NSData *data = [self valueForKey: key];

    id object = nil;

    if (data != nil) {
        object = [NSUnarchiver unarchiveObjectWithData: data];
    }

    return (object);

} // objectValueForKey


- (void) setStringValue: (NSString *) value
                 forKey: (NSString *) key
{
    [self setValue: value
          forKey: key];

} // setStringValue


- (NSString *) stringValueForKey: (NSString *) key
{
    NSString *string;
    string = [self valueForKey: key];

    return (string);

} // stringValueForKey


@end // BWConfigTemplate

